﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MongoExplorerTool.Infra.Connection;

namespace MongoExplorerTool.Infra.Tests.Connection
{
    [TestClass]
    public class ManagerTest
    {
        private string GetRandomString()
        {
            StringBuilder builder = new StringBuilder();
            Random random = new Random();
            char ch;
            for (int i = 0; i < 20; i++)
            {
                ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
                builder.Append(ch);
            }

            return builder.ToString();
        }

        [TestMethod]
        public void CreateComParametroNuloDeveLançarAExceçãoInvalidConnectionInfoException()
        {

            try
            {
                var manager = new Manager();
                var ret = manager.Create(null);
            }
            catch (Exception e)
            {
                Assert.IsInstanceOfType(e, typeof(InvalidConnectionInfoException));
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void CreateComParametroServerInválidoDeveLançarAExceçãoInvalidConnectionInfoException()
        {

            try
            {
                var manager = new Manager();
                var ret = manager.Create(new ConnectionInfo { Name = "Name", Password = "Password", Port = "Port", Server = string.Empty, Username = "Username" });
            }
            catch (Exception e)
            {
                Assert.IsInstanceOfType(e, typeof(InvalidConnectionInfoException));
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void CreateComParametroNameInválidoDeveLançarAExceçãoInvalidConnectionInfoException()
        {

            try
            {
                var manager = new Manager();
                var ret = manager.Create(new ConnectionInfo { Name = string.Empty, Password = "Password", Port = "Port", Server = "Server", Username = "Username" });
            }
            catch (Exception e)
            {
                Assert.IsInstanceOfType(e, typeof(InvalidConnectionInfoException));
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void CreateComParametroNameEServerInválidoDeveLançarAExceçãoInvalidConnectionInfoException()
        {

            try
            {
                var manager = new Manager();
                var ret = manager.Create(new ConnectionInfo { Name = string.Empty, Password = "Password", Port = "Port", Server = string.Empty, Username = "Username" });
            }
            catch (Exception e)
            {
                Assert.IsInstanceOfType(e, typeof(InvalidConnectionInfoException));
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void CreateComParametrosValidosDeveRetornarUmConnectionInfoValido()
        {
            try
            {
                var manager = new Manager();
                var param = new ConnectionInfo { Name = this.GetRandomString(), Password = "Password", Port = "Port", Server = "Server", Username = "Username" };
                var ret = manager.Create(param);

                Assert.AreEqual(param.Name, ret.Name);
                Assert.AreEqual(param.Password, ret.Password);
                Assert.AreEqual(param.Port, ret.Port);
                Assert.AreEqual(param.Server, ret.Server);
                Assert.AreEqual(param.Username, ret.Username);
            }
            catch
            {
                Assert.Fail();
            }
        }

        [TestMethod]
        public void GetByNameComParametroNameInválidoDeveRetornarArgumentNullExceptionComParameterName()
        {
            try
            {
                var manager = new Manager();
                var ret = manager.GetByName(string.Empty);
            }
            catch (Exception e)
            {
                Assert.IsInstanceOfType(e, typeof(ArgumentNullException));
                Assert.AreEqual((e as ArgumentNullException).ParamName, "name");
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void GetByNameComParametroNameVálidoDeveRetornarUmConnectionInfoValido()
        {
            try
            {
                var manager = new Manager();
                var param = new ConnectionInfo { Name = this.GetRandomString(), Password = "Password", Port = "Port", Server = "Server", Username = "Username"};
                var ret = manager.Create(param);


                manager = new Manager();
                var get = manager.GetByName(param.Name);

                Assert.AreEqual(get.Name, ret.Name);
                Assert.AreEqual(get.Password, ret.Password);
                Assert.AreEqual(get.Port, ret.Port);
                Assert.AreEqual(get.Server, ret.Server);
                Assert.AreEqual(get.Username, ret.Username);
            }
            catch(Exception e)
            {
                Assert.Fail();
            }
        }

        [TestMethod]
        public void DeleteByNameComParametroNameInválidoDeveRetornarArgumentNullExceptionComParameterName()
        {
            try
            {
                var manager = new Manager();
                manager.DeleteByName(string.Empty);
            }
            catch (Exception e)
            {
                Assert.IsInstanceOfType(e, typeof(ArgumentNullException));
                Assert.AreEqual((e as ArgumentNullException).ParamName, "name");
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void DeleteByNameComParametroNameVálidoDeveRemoverDoXmlAConnectionInfo()
        {
            try
            {
                var manager = new Manager();
                var param = new ConnectionInfo { Name = this.GetRandomString(), Password = "Password", Port = "Port", Server = "Server", Username = "Username" };
                var ret = manager.Create(param);


                manager = new Manager();
                manager.DeleteByName(param.Name);

                manager = new Manager();
                var removed = manager.GetByName(param.Name);
                Assert.IsNull(removed);

            }
            catch (Exception e)
            {
                Assert.Fail();
            }
        }

        [TestMethod]
        public void ListDeveretornarMaisDoQue5Itens()
        {
            try
            {
                var manager = new Manager();
                for (int i = 0; i < 8; i++)
                {
                    var param = new ConnectionInfo { Name = i.ToString() + "-" + DateTime.Now.ToString(), Password = "Password", Port = "Port", Server = "Server", Username = "Username" };
                    var ret = manager.Create(param); 
                }

                manager = new Manager();

                Assert.IsTrue(manager.List().Count > 5);
            }
            catch
            {
                Assert.Fail();
            }
        }
    }
}
